ποΈGitΠ―ΡΠ°ποΈ
Node / meshtastic / Meshtastic-Android / files / feature / firmware / src / commonMain / kotlin / org / meshtastic / feature / firmware / ota / dfu / SecureDfuProtocol.kt
Displaying Raw β’ Download
feature/firmware/src/commonMain/kotlin/org/meshtastic/feature/firmware/ota/dfu/SecureDfuProtocol.kt 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 13.77 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffMagicNumberTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffReturnCountTa5d6ff"Tb4b4b4)
Tff7b72package T7ee787org.meshtastic.feature.firmware.ota.dfu
Tff7b72import T7ee787kotlinx.serialization.SerialName
Tff7b72import T7ee787kotlinx.serialization.Serializable
Tff7b72import T7ee787kotlin.uuid.Uuid
T8b949e// ---------------------------------------------------------------------------
T8b949e// Nordic Secure DFU β service and characteristic UUIDs
T8b949e// ---------------------------------------------------------------------------
Tff7b72internal Tff7b72object T56d364SecureDfuUuids Tb4b4b4{
T8b949e/** Main DFU service β present in both normal mode (buttonless) and DFU mode. */
Tff7b72val Te6edf3SERVICETb4b4b4: Te6edf3Uuid Tff7b72= Te6edf3UuidTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ff0000FE59-0000-1000-8000-00805F9B34FBTa5d6ff"Tb4b4b4)
T8b949e/** Control Point: write opcodes WITH_RESPONSE, receive notifications. */
Tff7b72val Te6edf3CONTROL_POINTTb4b4b4: Te6edf3Uuid Tff7b72= Te6edf3UuidTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ff8EC90001-F315-4F60-9FB8-838830DAEA50Ta5d6ff"Tb4b4b4)
T8b949e/** Packet: write firmware/init data WITHOUT_RESPONSE. */
Tff7b72val Te6edf3PACKETTb4b4b4: Te6edf3Uuid Tff7b72= Te6edf3UuidTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ff8EC90002-F315-4F60-9FB8-838830DAEA50Ta5d6ff"Tb4b4b4)
T8b949e/** Buttonless DFU β no bond required. Write 0x01 to reboot into DFU mode. */
Tff7b72val Te6edf3BUTTONLESS_NO_BONDSTb4b4b4: Te6edf3Uuid Tff7b72= Te6edf3UuidTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ff8EC90003-F315-4F60-9FB8-838830DAEA50Ta5d6ff"Tb4b4b4)
Tb4b4b4}
T8b949e/**
* Nordic Legacy DFU service UUIDs (also used by Adafruit's `BLEDfu` helper class). Meshtastic firmware exposes this
* service when built **without** `BLE_DFU_SECURE`. The buttonless trigger is a single write of `0x01` (`START_DFU`) to
* the Control Point characteristic; the device then disconnects and reboots into the bootloader (which itself runs
* Secure DFU on modern Adafruit/oltaco bootloaders).
*
* Reference: `Adafruit_nRF52_Arduino/libraries/Bluefruit52Lib/src/services/BLEDfu.cpp`.
*/
Tff7b72internal Tff7b72object T56d364LegacyDfuUuids Tb4b4b4{
T8b949e/** Legacy DFU service β exposed by app firmware to trigger reboot into the bootloader. */
Tff7b72val Te6edf3SERVICETb4b4b4: Te6edf3Uuid Tff7b72= Te6edf3UuidTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ff00001530-1212-EFDE-1523-785FEABCD123Ta5d6ff"Tb4b4b4)
T8b949e/**
* Control Point: NOTIFY + WRITE. Notifications must be subscribed before writing or the device returns
* `ATTERR_CPS_CCCD_CONFIG_ERROR`.
*/
Tff7b72val Te6edf3CONTROL_POINTTb4b4b4: Te6edf3Uuid Tff7b72= Te6edf3UuidTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ff00001531-1212-EFDE-1523-785FEABCD123Ta5d6ff"Tb4b4b4)
Tb4b4b4}
T8b949e/** Secure DFU buttonless trigger: single-byte `0x01` (START_DFU) to FE59 service. */
Tff7b72internal Tff7b72const Tff7b72val Te6edf3BUTTONLESS_ENTER_BOOTLOADERTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x01
T8b949e/**
* Legacy DFU buttonless trigger payload per Nordic's `LegacyButtonlessDfuImpl.java:53`: `[OP_CODE_START_DFU=0x01,
* IMAGE_TYPE_APPLICATION=0x04]`. The Adafruit `BLEDfu` (and original Nordic SDK 6.x bootloader) require both bytes β
* sending only the opcode is a spec violation that some bootloader builds silently drop.
*/
Tff7b72internal Tff7b72val Te6edf3LEGACY_BUTTONLESS_ENTER_BOOTLOADERTb4b4b4: Te6edf3ByteArray Tff7b72= Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x04Tb4b4b4)
T8b949e// ---------------------------------------------------------------------------
T8b949e// Protocol opcodes
T8b949e// ---------------------------------------------------------------------------
Tff7b72internal Tff7b72object T56d364DfuOpcode Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3CREATETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x01
Tff7b72const Tff7b72val Te6edf3SET_PRNTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x02
Tff7b72const Tff7b72val Te6edf3CALCULATE_CHECKSUMTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x03
Tff7b72const Tff7b72val Te6edf3EXECUTETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x04
Tff7b72const Tff7b72val Te6edf3SELECTTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x06
Tff7b72const Tff7b72val Te6edf3ABORTTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x0C
Tff7b72const Tff7b72val Te6edf3RESPONSE_CODETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x60
Tb4b4b4}
Tff7b72internal Tff7b72object T56d364DfuObjectType Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3COMMANDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x01 T8b949e// init packet (.dat)
Tff7b72const Tff7b72val Te6edf3DATATb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x02 T8b949e// firmware binary (.bin)
Tb4b4b4}
Tff7b72internal Tff7b72object T56d364DfuResultCode Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3SUCCESSTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x01
Tff7b72const Tff7b72val Te6edf3OP_CODE_NOT_SUPPORTEDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x02
Tff7b72const Tff7b72val Te6edf3INVALID_PARAMETERTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x03
Tff7b72const Tff7b72val Te6edf3INSUFFICIENT_RESOURCESTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x04
Tff7b72const Tff7b72val Te6edf3INVALID_OBJECTTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x05
Tff7b72const Tff7b72val Te6edf3UNSUPPORTED_TYPETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x07
Tff7b72const Tff7b72val Te6edf3OPERATION_NOT_PERMITTEDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x08
Tff7b72const Tff7b72val Te6edf3OPERATION_FAILEDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x0A
Tff7b72const Tff7b72val Te6edf3EXT_ERRORTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x0B
Tb4b4b4}
T8b949e/**
* Extended error codes returned when [DfuResultCode.EXT_ERROR] (0x0B) is the result code. An additional byte follows in
* the response payload.
*/
Tff7b72internal Tff7b72object T56d364DfuExtendedError Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3WRONG_COMMAND_FORMATTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x02
Tff7b72const Tff7b72val Te6edf3UNKNOWN_COMMANDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x03
Tff7b72const Tff7b72val Te6edf3INIT_COMMAND_INVALIDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x04
Tff7b72const Tff7b72val Te6edf3FW_VERSION_FAILURETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x05
Tff7b72const Tff7b72val Te6edf3HW_VERSION_FAILURETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x06
Tff7b72const Tff7b72val Te6edf3SD_VERSION_FAILURETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x07
Tff7b72const Tff7b72val Te6edf3SIGNATURE_MISSINGTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x08
Tff7b72const Tff7b72val Te6edf3WRONG_HASH_TYPETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x09
Tff7b72const Tff7b72val Te6edf3HASH_FAILEDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x0A
Tff7b72const Tff7b72val Te6edf3WRONG_SIGNATURE_TYPETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x0B
Tff7b72const Tff7b72val Te6edf3VERIFICATION_FAILEDTb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x0C
Tff7b72const Tff7b72val Te6edf3INSUFFICIENT_SPACETb4b4b4: Tffa657Byte Tff7b72= T79c0ff0Te6edf3x0D
Tff7b72fun Td2a8ffdescribeTb4b4b4(Te6edf3codeTb4b4b4: Tffa657ByteTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Tff7b72when Tb4b4b4(Te6edf3codeTb4b4b4) Tb4b4b4{
Te6edf3WRONG_COMMAND_FORMAT Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffWrong command formatTa5d6ff"
Te6edf3UNKNOWN_COMMAND Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffUnknown commandTa5d6ff"
Te6edf3INIT_COMMAND_INVALID Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffInit command invalidTa5d6ff"
Te6edf3FW_VERSION_FAILURE Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffFW version failureTa5d6ff"
Te6edf3HW_VERSION_FAILURE Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffHW version failureTa5d6ff"
Te6edf3SD_VERSION_FAILURE Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffSD version failureTa5d6ff"
Te6edf3SIGNATURE_MISSING Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffSignature missingTa5d6ff"
Te6edf3WRONG_HASH_TYPE Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffWrong hash typeTa5d6ff"
Te6edf3HASH_FAILED Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffHash failedTa5d6ff"
Te6edf3WRONG_SIGNATURE_TYPE Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffWrong signature typeTa5d6ff"
Te6edf3VERIFICATION_FAILED Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffVerification failedTa5d6ff"
Te6edf3INSUFFICIENT_SPACE Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffInsufficient spaceTa5d6ff"
Tff7b72else Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffUnknown extended error 0xTffd700${Te6edf3codeTb4b4b4.Te6edf3toUByteTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff"
Tb4b4b4}
Tb4b4b4}
T8b949e// ---------------------------------------------------------------------------
T8b949e// Response parsing
T8b949e// ---------------------------------------------------------------------------
T8b949e/** Parsed notification from the DFU Control Point characteristic. */
Tff7b72internal Tff7b72sealed Tff7b72class T56d364DfuResponse Tb4b4b4{
T8b949e/** Simple success (CREATE, SET_PRN, EXECUTE, ABORT). */
Tff7b72data Tff7b72class T56d364SuccessTb4b4b4(Tff7b72val Te6edf3opcodeTb4b4b4: Tffa657ByteTb4b4b4) Tb4b4b4: Te6edf3DfuResponseTb4b4b4(Tb4b4b4)
T8b949e/** Response to SELECT opcode β carries the current object's state. */
Tff7b72data Tff7b72class T56d364SelectResultTb4b4b4(Tff7b72val Te6edf3opcodeTb4b4b4: Tffa657ByteTb4b4b4, Tff7b72val Te6edf3maxSizeTb4b4b4: Tffa657IntTb4b4b4, Tff7b72val Te6edf3offsetTb4b4b4: Tffa657IntTb4b4b4, Tff7b72val Te6edf3crc32Tb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4: Te6edf3DfuResponseTb4b4b4(Tb4b4b4)
T8b949e/** Response to CALCULATE_CHECKSUM β carries accumulated offset + CRC. */
Tff7b72data Tff7b72class T56d364ChecksumResultTb4b4b4(Tff7b72val Te6edf3offsetTb4b4b4: Tffa657IntTb4b4b4, Tff7b72val Te6edf3crc32Tb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4: Te6edf3DfuResponseTb4b4b4(Tb4b4b4)
T8b949e/** The device rejected the opcode with a non-success result code. */
Tff7b72data Tff7b72class T56d364FailureTb4b4b4(Tff7b72val Te6edf3opcodeTb4b4b4: Tffa657ByteTb4b4b4, Tff7b72val Te6edf3resultCodeTb4b4b4: Tffa657ByteTb4b4b4, Tff7b72val Te6edf3extendedErrorTb4b4b4: Tffa657Byte? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4: Te6edf3DfuResponseTb4b4b4(Tb4b4b4)
T8b949e/** Unrecognised bytes β logged, treated as an error. */
Tff7b72data Tff7b72class T56d364UnknownTb4b4b4(Tff7b72val Te6edf3rawTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tb4b4b4: Te6edf3DfuResponseTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72override Tff7b72fun Td2a8ffequalsTb4b4b4(Te6edf3otherTb4b4b4: Tffa657Any?Tb4b4b4) Tff7b72= Te6edf3other Tff7b72is Te6edf3Unknown Tff7b72&Tff7b72& Te6edf3rawTb4b4b4.Te6edf3contentEqualsTb4b4b4(Te6edf3otherTb4b4b4.Te6edf3rawTb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffhashCodeTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3rawTb4b4b4.Te6edf3contentHashCodeTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72fun Td2a8ffparseTb4b4b4(Te6edf3dataTb4b4b4: Te6edf3ByteArrayTb4b4b4)Tb4b4b4: Te6edf3DfuResponse Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4.Te6edf3size Tff7b72< T79c0ff3 Tff7b72|Tff7b72| Te6edf3dataTff7b72[T79c0ff0Tff7b72] Tff7b72!Tff7b72= Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4) Tff7b72return Te6edf3UnknownTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72val Te6edf3opcode Tff7b72= Te6edf3dataTff7b72[T79c0ff1Tff7b72]
Tff7b72val Te6edf3result Tff7b72= Te6edf3dataTff7b72[T79c0ff2Tff7b72]
Tff7b72if Tb4b4b4(Te6edf3result Tff7b72!Tff7b72= Te6edf3DfuResultCodeTb4b4b4.Te6edf3SUCCESSTb4b4b4) Tb4b4b4{
T8b949e// Extract the extended error byte when present (result == 0x0B and byte at index 3).
Tff7b72val Te6edf3extError Tff7b72= Tff7b72if Tb4b4b4(Te6edf3result Tff7b72=Tff7b72= Te6edf3DfuResultCodeTb4b4b4.Te6edf3EXT_ERROR Tff7b72&Tff7b72& Te6edf3dataTb4b4b4.Te6edf3size Tff7b72>Tff7b72= T79c0ff4Tb4b4b4) Te6edf3dataTff7b72[T79c0ff3Tff7b72] Tff7b72else Tff7b72null
Tff7b72return Te6edf3FailureTb4b4b4(Te6edf3opcodeTb4b4b4, Te6edf3resultTb4b4b4, Te6edf3extErrorTb4b4b4)
Tb4b4b4}
Tff7b72return Tff7b72when Tb4b4b4(Te6edf3opcodeTb4b4b4) Tb4b4b4{
Te6edf3DfuOpcodeTb4b4b4.Te6edf3SELECT Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4.Te6edf3size Tff7b72< T79c0ff1T79c0ff5Tb4b4b4) Tff7b72return Te6edf3FailureTb4b4b4(Te6edf3opcodeTb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_PARAMETERTb4b4b4)
Te6edf3SelectResultTb4b4b4(
Te6edf3opcode Tff7b72= Te6edf3opcodeTb4b4b4,
Te6edf3maxSize Tff7b72= Te6edf3dataTb4b4b4.Te6edf3readIntLeTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4,
Te6edf3offset Tff7b72= Te6edf3dataTb4b4b4.Te6edf3readIntLeTb4b4b4(T79c0ff7Tb4b4b4)Tb4b4b4,
Te6edf3crc32 Tff7b72= Te6edf3dataTb4b4b4.Te6edf3readIntLeTb4b4b4(T79c0ff1T79c0ff1Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3DfuOpcodeTb4b4b4.Te6edf3CALCULATE_CHECKSUM Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4.Te6edf3size Tff7b72< T79c0ff1T79c0ff1Tb4b4b4) Tff7b72return Te6edf3FailureTb4b4b4(Te6edf3opcodeTb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_PARAMETERTb4b4b4)
Te6edf3ChecksumResultTb4b4b4(Te6edf3offset Tff7b72= Te6edf3dataTb4b4b4.Te6edf3readIntLeTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4, Te6edf3crc32 Tff7b72= Te6edf3dataTb4b4b4.Te6edf3readIntLeTb4b4b4(T79c0ff7Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Te6edf3SuccessTb4b4b4(Te6edf3opcodeTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// ---------------------------------------------------------------------------
T8b949e// Byte-level helpers
T8b949e// ---------------------------------------------------------------------------
Tff7b72internal Tff7b72fun Te6edf3ByteArrayTb4b4b4.Td2a8ffreadIntLeTb4b4b4(Te6edf3offsetTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657Int Tff7b72= Tb4b4b4(Tff7b72thisTff7b72[Te6edf3offsetTff7b72]Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4) Te6edf3or
Tb4b4b4(Tb4b4b4(Tff7b72thisTff7b72[Te6edf3offset Tff7b72+ T79c0ff1Tff7b72]Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4) Te6edf3shl T79c0ff8Tb4b4b4) Te6edf3or
Tb4b4b4(Tb4b4b4(Tff7b72thisTff7b72[Te6edf3offset Tff7b72+ T79c0ff2Tff7b72]Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4) Te6edf3shl T79c0ff1T79c0ff6Tb4b4b4) Te6edf3or
Tb4b4b4(Tb4b4b4(Tff7b72thisTff7b72[Te6edf3offset Tff7b72+ T79c0ff3Tff7b72]Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4) Te6edf3shl T79c0ff2T79c0ff4Tb4b4b4)
Tff7b72internal Tff7b72fun Td2a8ffintToLeBytesTb4b4b4(Te6edf3valueTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3ByteArray Tff7b72= Te6edf3byteArrayOfTb4b4b4(
Tb4b4b4(Te6edf3value Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4)Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4(Tb4b4b4(Te6edf3value Te6edf3ushr T79c0ff8Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4)Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4(Tb4b4b4(Te6edf3value Te6edf3ushr T79c0ff1T79c0ff6Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4)Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4(Tb4b4b4(Te6edf3value Te6edf3ushr T79c0ff2T79c0ff4Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTb4b4b4)Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
T8b949e// ---------------------------------------------------------------------------
T8b949e// CRC-32 (IEEE 802.3 / PKZIP) β pure Kotlin, no platform dependencies
T8b949e// ---------------------------------------------------------------------------
Tff7b72internal Tff7b72object T56d364DfuCrc32 Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3TABLE Tff7b72=
Te6edf3IntArrayTb4b4b4(T79c0ff2T79c0ff5T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3also Tb4b4b4{ Te6edf3table Tff7b72-Tff7b72>
Tff7b72for Tb4b4b4(Te6edf3n Tff7b72in T79c0ff0.Tb4b4b4.T79c0ff2T79c0ff5T79c0ff5Tb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3c Tff7b72= Te6edf3n
Te6edf3repeatTb4b4b4(T79c0ff8Tb4b4b4) Tb4b4b4{ Te6edf3c Tff7b72= Tff7b72if Tb4b4b4(Te6edf3c Te6edf3and T79c0ff1 Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4(Te6edf3c Te6edf3ushr T79c0ff1Tb4b4b4) Te6edf3xor T79c0ff0Te6edf3xEDB88320Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4) Tff7b72else Te6edf3c Te6edf3ushr T79c0ff1 Tb4b4b4}
Te6edf3tableTff7b72[Te6edf3nTff7b72] Tff7b72= Te6edf3c
Tb4b4b4}
Tb4b4b4}
T8b949e/** Compute CRC-32 over [data], optionally seeding from a previous [seed] (pass prior result). */
Tff7b72fun Td2a8ffcalculateTb4b4b4(Te6edf3dataTb4b4b4: Te6edf3ByteArrayTb4b4b4, Te6edf3offsetTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4, Te6edf3lengthTb4b4b4: Tffa657Int Tff7b72= Te6edf3dataTb4b4b4.Te6edf3size Tff7b72- Te6edf3offsetTb4b4b4, Te6edf3seedTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4)Tb4b4b4: Tffa657Int Tb4b4b4{
Tff7b72var Te6edf3crc Tff7b72= Te6edf3seedTb4b4b4.Te6edf3invTb4b4b4(Tb4b4b4)
Tff7b72for Tb4b4b4(Te6edf3i Tff7b72in Te6edf3offset Te6edf3until Te6edf3offset Tff7b72+ Te6edf3lengthTb4b4b4) Tb4b4b4{
Te6edf3crc Tff7b72= Tb4b4b4(Te6edf3crc Te6edf3ushr T79c0ff8Tb4b4b4) Te6edf3xor Te6edf3TABLETff7b72[Tb4b4b4(Te6edf3crc Te6edf3xor Te6edf3dataTff7b72[Te6edf3iTff7b72]Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3and T79c0ff0Te6edf3xFFTff7b72]
Tb4b4b4}
Tff7b72return Te6edf3crcTb4b4b4.Te6edf3invTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e// ---------------------------------------------------------------------------
T8b949e// DFU zip package contents
T8b949e// ---------------------------------------------------------------------------
T8b949e/** Contents extracted from a Nordic DFU .zip package. */
Tff7b72data Tff7b72class T56d364DfuZipPackageTb4b4b4(
Tff7b72val Te6edf3initPacketTb4b4b4: Te6edf3ByteArrayTb4b4b4, T8b949e// .dat β signed init packet
Tff7b72val Te6edf3firmwareTb4b4b4: Te6edf3ByteArrayTb4b4b4, T8b949e// .bin β application binary
Tb4b4b4) Tb4b4b4{
Tff7b72override Tff7b72fun Td2a8ffequalsTb4b4b4(Te6edf3otherTb4b4b4: Tffa657Any?Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72this Tff7b72=Tff7b72=Tff7b72= Te6edf3otherTb4b4b4) Tff7b72return Tff7b72true
Tff7b72if Tb4b4b4(Te6edf3other Tff7b72!is Te6edf3DfuZipPackageTb4b4b4) Tff7b72return Tff7b72false
Tff7b72return Te6edf3initPacketTb4b4b4.Te6edf3contentEqualsTb4b4b4(Te6edf3otherTb4b4b4.Te6edf3initPacketTb4b4b4) Tff7b72&Tff7b72& Te6edf3firmwareTb4b4b4.Te6edf3contentEqualsTb4b4b4(Te6edf3otherTb4b4b4.Te6edf3firmwareTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffhashCodeTb4b4b4(Tb4b4b4) Tff7b72= T79c0ff3T79c0ff1 Tff7b72* Te6edf3initPacketTb4b4b4.Te6edf3contentHashCodeTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3firmwareTb4b4b4.Te6edf3contentHashCodeTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e// ---------------------------------------------------------------------------
T8b949e// Manifest (kotlinx.serialization)
T8b949e// ---------------------------------------------------------------------------
Tf0883e@Serializable Tff7b72internal Tff7b72data Tff7b72class T56d364DfuManifestTb4b4b4(Tff7b72val Te6edf3manifestTb4b4b4: Te6edf3DfuManifestContentTb4b4b4)
Tf0883e@Serializable
Tff7b72internal Tff7b72data Tff7b72class T56d364DfuManifestContentTb4b4b4(
Tff7b72val Te6edf3applicationTb4b4b4: Te6edf3DfuManifestEntry? Tff7b72= Tff7b72nullTb4b4b4,
Tff7b72val Te6edf3bootloaderTb4b4b4: Te6edf3DfuManifestEntry? Tff7b72= Tff7b72nullTb4b4b4,
Tf0883e@SerialNameTb4b4b4(Ta5d6ff"Ta5d6ffsoftdevice_bootloaderTa5d6ff"Tb4b4b4) Tff7b72val Te6edf3softdeviceBootloaderTb4b4b4: Te6edf3DfuManifestEntry? Tff7b72= Tff7b72nullTb4b4b4,
Tff7b72val Te6edf3softdeviceTb4b4b4: Te6edf3DfuManifestEntry? Tff7b72= Tff7b72nullTb4b4b4,
Tb4b4b4) Tb4b4b4{
T8b949e/** First non-null entry in priority order. */
Tff7b72val Te6edf3primaryEntryTb4b4b4: Te6edf3DfuManifestEntry?
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3application Tff7b72?: Te6edf3softdeviceBootloader Tff7b72?: Te6edf3bootloader Tff7b72?: Te6edf3softdevice
T8b949e/** Number of image entries present. >1 means a combined package, of which only [primaryEntry] is flashed. */
Tff7b72val Te6edf3imageCountTb4b4b4: Tffa657Int
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3listOfNotNullTb4b4b4(Te6edf3applicationTb4b4b4, Te6edf3softdeviceBootloaderTb4b4b4, Te6edf3bootloaderTb4b4b4, Te6edf3softdeviceTb4b4b4)Tb4b4b4.Te6edf3size
Tb4b4b4}
Tf0883e@Serializable
Tff7b72internal Tff7b72data Tff7b72class T56d364DfuManifestEntryTb4b4b4(
Tf0883e@SerialNameTb4b4b4(Ta5d6ff"Ta5d6ffbin_fileTa5d6ff"Tb4b4b4) Tff7b72val Te6edf3binFileTb4b4b4: Tffa657StringTb4b4b4,
Tf0883e@SerialNameTb4b4b4(Ta5d6ff"Ta5d6ffdat_fileTa5d6ff"Tb4b4b4) Tff7b72val Te6edf3datFileTb4b4b4: Tffa657StringTb4b4b4,
Tb4b4b4)
T8b949e// ---------------------------------------------------------------------------
T8b949e// Exceptions
T8b949e// ---------------------------------------------------------------------------
T8b949e/** Errors specific to the Nordic Secure DFU protocol. */
Tff7b72sealed Tff7b72class T56d364DfuExceptionTb4b4b4(Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4, Te6edf3causeTb4b4b4: Te6edf3Throwable? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4: Te6edf3ExceptionTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3causeTb4b4b4) Tb4b4b4{
T8b949e/** BLE connection to the DFU target could not be established or was lost. */
Tff7b72class T56d364ConnectionFailedTb4b4b4(Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4, Te6edf3causeTb4b4b4: Te6edf3Throwable? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4: Te6edf3DfuExceptionTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3causeTb4b4b4)
T8b949e/** The DFU zip package is malformed or missing required entries. */
Tff7b72class T56d364InvalidPackageTb4b4b4(Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4: Te6edf3DfuExceptionTb4b4b4(Te6edf3messageTb4b4b4)
T8b949e/** The device returned a DFU error response for a given opcode. */
Tff7b72class T56d364ProtocolErrorTb4b4b4(Tff7b72val Te6edf3opcodeTb4b4b4: Tffa657ByteTb4b4b4, Tff7b72val Te6edf3resultCodeTb4b4b4: Tffa657ByteTb4b4b4, Tff7b72val Te6edf3extendedErrorTb4b4b4: Tffa657Byte? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4:
Te6edf3DfuExceptionTb4b4b4(
Te6edf3buildString Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ffDFU protocol error: opcode=0xTffd700${Te6edf3opcodeTb4b4b4.Te6edf3toUByteTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff Ta5d6ff"Tb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ffresult=0xTffd700${Te6edf3resultCodeTb4b4b4.Te6edf3toUByteTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3extendedError Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff ext=Tffd700${Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3extendedErrorTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
T8b949e/** CRC-32 of the transferred data does not match the device's computed checksum. */
Tff7b72class T56d364ChecksumMismatchTb4b4b4(Te6edf3expectedTb4b4b4: Tffa657IntTb4b4b4, Te6edf3actualTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4:
Te6edf3DfuExceptionTb4b4b4(
Ta5d6ff"Ta5d6ffCRC-32 mismatch: expected 0xTffd700${Te6edf3expectedTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff8Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffgot 0xTffd700${Te6edf3actualTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff8Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
T8b949e/** A DFU operation did not complete within the expected time window. */
Tff7b72class T56d364TimeoutTb4b4b4(Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4: Te6edf3DfuExceptionTb4b4b4(Te6edf3messageTb4b4b4)
T8b949e/** Data transfer to the device failed for a non-protocol reason (e.g. BLE write error). */
Tff7b72class T56d364TransferFailedTb4b4b4(Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4, Te6edf3causeTb4b4b4: Te6edf3Throwable? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4: Te6edf3DfuExceptionTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3causeTb4b4b4)
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.1s